package bll

import (
	"context"
	"fmt"
	"gitlab.local/backend/proto/dto"
	"go-micro.dev/v4/client"
	"ota/client/grpc"
	"ota/config"
	"ota/errors"
	"ota/lib/trace_log"
	"strings"
)

var (
	simulatorInstance = &simulator{}
)

type upgradeV2 struct {
}

/*
bsc22开头的设备的升级步骤
发送升级设置参数(告诉设备可以请求升级包)
*/

// 0x01 设置升级参数
func (u *upgradeV2) doUpgrade0x01(ctx context.Context, id uint64, sn string, deviceType uint8, fileLength uint32) error {

	s := config.Conf.Simulator
	if s.Enable {
		return simulatorInstance.doUpgrade0x01(ctx, id, sn, deviceType, fileLength)
	}

	//id = 491052011223037314
	return u.doUpgrade(ctx, &dto.UpgradeBSC22Data{
		UpgradeCmd: dto.BSC22UpgradeCmdType_Cmd0x01,
		DeviceType: int32(deviceType),
		Id:         id,
		Sn:         sn,
		BindLength: fileLength,
		Body:       []byte{0x01, 0x00, 0x00, 0x00},
	})
}

func (u *upgradeV2) dealUpgrade0x00(ctx context.Context, id uint64, sn string, deviceType uint8, bindAddress, bindLength uint32, data []byte) error {

	s := config.Conf.Simulator
	if s.Enable {
		return simulatorInstance.dealUpgrade0x00(ctx, id, sn, deviceType, bindAddress, bindLength, data)
	}
	return nil
}

// 0x02 请求应答包
/*
发送: 服务器  --- 0x02 --->  终端
应答: 终端   --- 0x02 --->  服务器
*/
func (u *upgradeV2) dealUpgrade0x02(ctx context.Context, id uint64, sn string, deviceType uint8, bindAddress, bindLength uint32, data []byte) error {

	s := config.Conf.Simulator
	if s.Enable {
		return simulatorInstance.doUpgrade0x02(ctx, id, sn, deviceType, bindAddress, bindLength, data)
	}

	sendPacket := &dto.UpgradeBSC22Data{
		UpgradeCmd:  dto.BSC22UpgradeCmdType_Cmd0x02,
		DeviceType:  int32(deviceType),
		Id:          id,
		Sn:          sn,
		BindLength:  bindLength,
		BindAddress: bindAddress,
		Body:        data,
	}

	sendPacket.Crc32 = BuildPacket(sendPacket).Crc32

	trace_log.DebugLogger(sn, "---- dealUpgrade0x02:", strings.ToLower(fmt.Sprintf("0x%X", BuildPacket(sendPacket).ToHexBytes())))

	return u.doUpgrade(ctx, sendPacket)
}

func (u *upgradeV2) doUpgrade(ctx context.Context, bsc22 *dto.UpgradeBSC22Data) error {

	return RpcCall(bsc22.Sn, func(addr string, err error) error {
		if err != nil {
			return err
		}

		_, err = grpc.Cmd.UpgradeBSC22(ctx, bsc22, func(options *client.CallOptions) {
			options.Address = []string{addr}
		})
		if err != nil {
			return errors.DeviceCommandFailed.Error()
		}
		return err
	})
}
